package com.zmn.oms.zmn.business.impl.work;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.company.CompanyDRO;
import com.zmn.base.common.data.dubbo.interfaces.company.CompanyListRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.categ.CategProductGroupDRO;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.DefaultEcProductQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.common.query.categ.CategProductGroupQuery;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServProductListRemoteService;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.engstock.common.model.dro.StockItemDRO;
import com.zmn.mos.common.dio.order.list.PreOrderProductNumberQueryDIO;
import com.zmn.mos.common.dro.order.list.PreOrderProductNumberDRO;
import com.zmn.mos.dubbo.interfaces.order.OrderListRemoteService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderDistributeConsts;
import com.zmn.oms.common.constant.OrderGateTypeConsts;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.order.GridCompanyQueryBO;
import com.zmn.oms.model.bo.product.ProductBO;
import com.zmn.oms.model.bo.stock.DistributeMasterQueryBaseBO;
import com.zmn.oms.model.bo.stock.MasterStockQueryBO;
import com.zmn.oms.model.bo.stock.StockDefaultDutyTimeQueryBO;
import com.zmn.oms.model.bo.stock.StockScheduleTimeBO;
import com.zmn.oms.model.dto.order.GridCompanyInfoDTO;
import com.zmn.oms.model.entity.work.DistributeMasterQuery;
import com.zmn.oms.model.vo.work.DistributeVO;
import com.zmn.oms.model.vo.work.ZsOrderDistributeVO;
import com.zmn.oms.model.vo.work.schedule.OrderScheduleVO;
import com.zmn.oms.zmn.business.interfaces.order.ZsOrderBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkStockScheduleBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName ZsOrderWorkStockScheduleBServiceImpl
 * @description:
 * @author: wangyanci
 * @create: 2022-01-12 11:27
 * @Version 1.0
 **/
@Slf4j
@Service
public class ZsOrderWorkStockScheduleBServiceImpl implements ZsOrderWorkStockScheduleBService {

    private static final char NOT_AVAILABLE = '0';
    private static final char AVAILABLE = '1';

    // 默认预约时间最大调用次数
    private static final Map<Integer, Integer> DEFAULT_DUTY_TIME_MAX_CALL_NUMBER = Maps.newHashMap();
    static {
        DEFAULT_DUTY_TIME_MAX_CALL_NUMBER.put(OrderGateTypeConsts.GATE_USER, 2);
        DEFAULT_DUTY_TIME_MAX_CALL_NUMBER.put(OrderGateTypeConsts.CHANNEL_APPLICATION, 1);
    }

    // 预约时间范围配置
    private static final Map<Integer, String> DUTY_TIME_RANGE_CONFIG = Maps.newHashMap();
    static {
        DUTY_TIME_RANGE_CONFIG.put(OrderGateTypeConsts.GATE_USER, "09:00-22:00");
        DUTY_TIME_RANGE_CONFIG.put(OrderGateTypeConsts.CHANNEL_APPLICATION, "00:00-23:59");
    }

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private ProductForeignListRemoteService productForeignListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private CategServProductListRemoteService categServProductListRemoteService;
    @DubboReference(version = com.zmn.mos.dubbo.utils.DubboConsts.INTERFACE_VERSION, timeout = 10000, check = false)
    private OrderListRemoteService orderListRemoteService;

    @Autowired
    private OrderStockBService orderStockBService;
    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;
    @Autowired
    private ZsOrderBService zsOrderBService;


    @Override
    public OrderScheduleVO getStockScheduleTimes(StockScheduleTimeBO stockScheduleTimeBO) throws OmsBaseException {
        OrderScheduleVO orderScheduleVO = new OrderScheduleVO();
        orderScheduleVO.setDate(DateUtil.toString(stockScheduleTimeBO.getDutyTime(), DateUtil.FORMAT_DATE));
        orderScheduleVO.setNowTime(DateUtil.getNowFormatted(DateUtil.FORMAT_DEFAULT));
        String times = OrderConsts.ORDER_SCHE_NONE_TIMES_96;
        orderScheduleVO.setTimes(times);

        // 判断是否小于当天
        Date curDate = DateUtil.getNow();
        int curDay = Integer.parseInt(DateUtil.toString(curDate, DateUtil.FORMAT_DATE2));
        int scheDay = Integer.parseInt(DateUtil.toString(stockScheduleTimeBO.getDutyTime(), DateUtil.FORMAT_DATE2));
        if (scheDay < curDay) {
            return orderScheduleVO;
        }
        // 1.处理参数
        this.processProductNumber(stockScheduleTimeBO);
        this.processDistributeMasterQuery(stockScheduleTimeBO);

        // 2.获取派单工程师集合
        DistributeMasterQuery distributeMasterQuery = BeanMapper.map(stockScheduleTimeBO, DistributeMasterQuery.class);
        log.info("获取预约推荐工程师列表 入参：{}", distributeMasterQuery);
        DistributeVO distributeVO = zsDistributeWorkBService.listDutyRecommendMaster(distributeMasterQuery);
        log.info("获取预约推荐工程师列表 出参：{}", distributeVO);
        if (Objects.isNull(distributeVO)) {
            return orderScheduleVO;
        }
        if (CollectionUtil.isNullOrEmpty(distributeVO.getMasterList())) {
            return orderScheduleVO;
        }
        List<Integer> masterIdList = distributeVO.getMasterList()
                .stream()
                .map(ZsOrderDistributeVO::getMasterId)
                .collect(Collectors.toList());
        if (CollectionUtil.isNullOrEmpty(masterIdList)) {
            return orderScheduleVO;
        }
        // 3.获取工程师库存
        MasterStockQueryBO masterStockQueryBO = MasterStockQueryBO
                .builder()
                .engineerIdList(masterIdList)
                .bizType(stockScheduleTimeBO.getBizType())
                .cityId(stockScheduleTimeBO.getCityId())
                .dutyTime(stockScheduleTimeBO.getDutyTime())
                .productNumber(stockScheduleTimeBO.getProductNumber())
                .servCategId(stockScheduleTimeBO.getServCategId())
                .showCategId(stockScheduleTimeBO.getShowCategId())
                .build();
        Map<Integer, List<StockItemDRO>> masterStockMap = orderStockBService.listMasterStock(masterStockQueryBO);
        times = this.getScheduleTimesByMasterStock(masterStockMap, stockScheduleTimeBO.getDutyTime());
        if (Objects.equals(times, OrderConsts.ORDER_SCHE_NONE_TIMES_96)) {
            return orderScheduleVO;
        }
        orderScheduleVO.setTimes(times);
        // 4.设置默认选中index
        if (scheDay == curDay) {
            Date defaultDutyTime = this.calculateDefaultDutyTime(times, stockScheduleTimeBO.getGeteType(), stockScheduleTimeBO.getDutyTime());
            if (Objects.nonNull(defaultDutyTime)) {
                String time = DateUtil.toString(defaultDutyTime, "HH:mm");
                orderScheduleVO.setDefaultActiveIndex(calculateIndex(time));
                orderScheduleVO.setDefaultActiveTime(DateUtil.toString(defaultDutyTime));
            }
        }
        return orderScheduleVO;
    }

    @Override
    public Map<Integer, Date> listStockDefaultDutyTime(List<StockDefaultDutyTimeQueryBO> stockDefaultDutyTimeQueries) throws OmsBaseException {
        log.info("ZsOrderWorkStockScheduleBServiceImpl.listStockDefaultDutyTime stockDefaultDutyTimeQueries={}", stockDefaultDutyTimeQueries);
        HashMap<Integer, Date> defaultDutyTimeMap = Maps.newHashMap();
        if (CollectionUtil.isNullOrEmpty(stockDefaultDutyTimeQueries)) {
            return defaultDutyTimeMap;
        }
        // 预约时间日期 小于 当前时间日期 不处理
        Iterator<StockDefaultDutyTimeQueryBO> iterator = stockDefaultDutyTimeQueries.iterator();
        while (iterator.hasNext()) {
            StockDefaultDutyTimeQueryBO next = iterator.next();
            Date dutyTime = next.getDutyTime();
            int duty = Integer.parseInt(DateUtil.toString(dutyTime, DateUtil.FORMAT_DATE2));
            int now = Integer.parseInt(DateUtil.toString(DateUtil.getNow(), DateUtil.FORMAT_DATE2));
            if (duty < now) {
                iterator.remove();
            }
        }

        // 1.处理参数
        for (StockDefaultDutyTimeQueryBO stockDefaultDutyTimeQuery : stockDefaultDutyTimeQueries) {
            this.processProductNumber(stockDefaultDutyTimeQuery);
            this.processDistributeMasterQuery(stockDefaultDutyTimeQuery);
        }
        // 记录调用次数
        HashMap<Integer, Integer> callNumberMap = Maps.newHashMap();
        for (StockDefaultDutyTimeQueryBO stockDefaultDutyTimeQuery : stockDefaultDutyTimeQueries) {
            callNumberMap.put(stockDefaultDutyTimeQuery.getShowProductId(), 0);
        }

        // 获取派单工程师集合、获取工程师库存、计算默认预约时间
        for (StockDefaultDutyTimeQueryBO stockDefaultDutyTimeQuery : stockDefaultDutyTimeQueries) {
            Integer callNumber = callNumberMap.get(stockDefaultDutyTimeQuery.getShowProductId());
            Integer maxNumber = DEFAULT_DUTY_TIME_MAX_CALL_NUMBER.get(stockDefaultDutyTimeQuery.getGeteType());
            if (Objects.isNull(maxNumber)) {
                continue;
            }

            while (callNumber < maxNumber) {
                // 调用次数加1
                callNumber++;
                callNumberMap.put(stockDefaultDutyTimeQuery.getShowProductId(), callNumber);
                // 获取可派工程师
                DistributeMasterQuery distributeMasterQuery = BeanMapper.map(stockDefaultDutyTimeQuery, DistributeMasterQuery.class);
                log.info("获取预约推荐工程师列表 入参：{}", distributeMasterQuery);
                DistributeVO distributeVO = zsDistributeWorkBService.listDutyRecommendMaster(distributeMasterQuery);
                log.info("获取预约推荐工程师列表 出参：{}", distributeVO);
                if (Objects.isNull(distributeVO)) {
                    // 顺延更换预约时间
                    stockDefaultDutyTimeQuery.setDutyTime(DateUtil.addDays(stockDefaultDutyTimeQuery.getDutyTime(), 1));
                    continue;
                }
                if (CollectionUtil.isNullOrEmpty(distributeVO.getMasterList())) {
                    // 顺延更换预约时间
                    stockDefaultDutyTimeQuery.setDutyTime(DateUtil.addDays(stockDefaultDutyTimeQuery.getDutyTime(), 1));
                    continue;
                }
                List<Integer> masterIdList = distributeVO.getMasterList()
                        .stream()
                        .map(ZsOrderDistributeVO::getMasterId)
                        .collect(Collectors.toList());
                if (CollectionUtil.isNullOrEmpty(masterIdList)) {
                    // 顺延更换预约时间
                    stockDefaultDutyTimeQuery.setDutyTime(DateUtil.addDays(stockDefaultDutyTimeQuery.getDutyTime(), 1));
                    continue;
                }

                // 3. 获取工程师库存
                MasterStockQueryBO masterStockQueryBO = MasterStockQueryBO
                        .builder()
                        .engineerIdList(masterIdList)
                        .bizType(stockDefaultDutyTimeQuery.getBizType())
                        .cityId(stockDefaultDutyTimeQuery.getCityId())
                        .dutyTime(stockDefaultDutyTimeQuery.getDutyTime())
                        .productNumber(stockDefaultDutyTimeQuery.getProductNumber())
                        .servCategId(stockDefaultDutyTimeQuery.getServCategId())
                        .showCategId(stockDefaultDutyTimeQuery.getShowCategId())
                        .build();
                Map<Integer, List<StockItemDRO>> masterStockMap = orderStockBService.listMasterStock(masterStockQueryBO);
                String times = this.getScheduleTimesByMasterStock(masterStockMap, stockDefaultDutyTimeQuery.getDutyTime());
                // 4. 计算预约时间
                Date dutyTime = this.calculateDefaultDutyTime(times, stockDefaultDutyTimeQuery.getGeteType(),stockDefaultDutyTimeQuery.getDutyTime());
                if (Objects.isNull(dutyTime)) {
                    // 顺延更换预约时间
                    stockDefaultDutyTimeQuery.setDutyTime(DateUtil.addDays(stockDefaultDutyTimeQuery.getDutyTime(), 1));
                    continue;
                }
                defaultDutyTimeMap.put(stockDefaultDutyTimeQuery.getShowProductId(), dutyTime);

                break;
            }
        }

        return defaultDutyTimeMap;
    }

    /**
     * 获取时间刻度
     * @param masterStockMap 工程师库存
     * @param dutyTime 库存日期
     * @return
     */
    private String getScheduleTimesByMasterStock(Map<Integer, List<StockItemDRO>> masterStockMap, Date dutyTime) {
        String times = OrderConsts.ORDER_SCHE_NONE_TIMES_96;

        // 校验日期
        Date now = DateUtil.getNow();
        int stockDay = Integer.parseInt(DateUtil.toString(dutyTime, DateUtil.FORMAT_DATE2));
        int nowDay = Integer.parseInt(DateUtil.toString(now, DateUtil.FORMAT_DATE2));
        if (stockDay < nowDay) {
            return times;
        }

        // 如果是当天，计算当前时间index，小于当前时间index 置为不可用
        String nowTime = DateUtil.toString(now, "HH:mm");
        int nowTimeIndex = calculateIndex(nowTime);
        boolean isNowDay = stockDay == nowDay;


        char[] timesCharArray = times.toCharArray();
        for (Map.Entry<Integer, List<StockItemDRO>> masterStockItem : masterStockMap.entrySet()) {
            List<StockItemDRO> stockItemDROList = masterStockItem.getValue();
            if (CollectionUtil.isNullOrEmpty(stockItemDROList)) {
                continue;
            }
            for (StockItemDRO stockItemDRO : stockItemDROList) {
                // 如果开始时间已经可用了，说明整个 timeList 已经有了（这些工程师库存都是一个产品组的库存时间）
                String startTime = stockItemDRO.getStartTime();
                int startTimeindex = calculateIndex(startTime);
                if (Objects.equals(timesCharArray[startTimeindex], AVAILABLE)) {
                    continue;
                }
                List<String> timeList = stockItemDRO.getTimeList();
                if (CollectionUtil.isNullOrEmpty(timeList)) {
                    continue;
                }
                for (String time : timeList) {
                    String[] split = time.split(" - ");
                    for (String s : split) {
                        int index = calculateIndex(s);
                        if (isNowDay) {
                            if (index > nowTimeIndex) {
                                timesCharArray[index] = AVAILABLE;
                            }
                        }else {
                            timesCharArray[index] = AVAILABLE;
                        }
                    }
                }
            }
        }
        times = new String(timesCharArray);
        return times;
    }

    /**
     *
     * @param times
     * @param geteType
     * @param dutyTime
     * 预约时间如果是今天 ：则 时分 变成当前时间，用于规则处理
     * 预约时间如果是今天以后 ：则 时分变成配置的开始时间，用于规则处理
     * @return
     */
    private Date calculateDefaultDutyTime(String times, int geteType, Date dutyTime) {
        log.info("times={},geteType={},dutyTime={}", times, geteType, DateUtil.toString(dutyTime));
        if (StringUtil.isBlank(times)) {
            return null;
        }
        if (Objects.equals(times, OrderConsts.ORDER_SCHE_NONE_TIMES_96)) {
            return null;
        }

        String timeRange = DUTY_TIME_RANGE_CONFIG.get(geteType);
        if (StringUtil.isBlank(timeRange)) {
            return null;
        }

        int dutyTimeDayInt = Integer.parseInt(DateUtil.toString(dutyTime, DateUtil.FORMAT_DATE2));
        int nowDayInt = Integer.parseInt(DateUtil.toString(DateUtil.getNow(), DateUtil.FORMAT_DATE2));


        Integer timeIndex = null;

        // 今天之后的处理方法
        if (dutyTimeDayInt > nowDayInt) {
            timeIndex = this.getNowAfterCalculateDefaultDutyTimeIndex(times, timeRange);
        }else {
            switch (geteType) {
                case OrderGateTypeConsts.GATE_USER: {
                    timeIndex = this.getUserCalculateDefaultDutyTimeIndex(times, timeRange);
                    break;
                }
                case OrderGateTypeConsts.CHANNEL_APPLICATION: {
                    timeIndex = this.getNowAfterCalculateDefaultDutyTimeIndex(times, timeRange);
                    break;
                }
                default:
                    return null;
            }
        }


        if (Objects.isNull(timeIndex)) {
            return null;
        }
        String dutyTimeStr = String.format("%s %s:00", DateUtil.toString(dutyTime, DateUtil.FORMAT_DATE), calculateTime(timeIndex));
        return DateUtil.dateFormatToDate(dutyTimeStr, DateUtil.FORMAT_DEFAULT);
    }

    /**
     * @param times
     * @param timeRange 09:00-22:00
     * @return
     */
    private Integer getUserCalculateDefaultDutyTimeIndex(String times, String timeRange) {
        String[] split = timeRange.split("-");
        String timeRangeStartTime = split[0];
        String timeRangeEndTime = split[1];

        Date now = DateUtil.getNow();
        String nowTime = DateUtil.toString(now, "HH:mm");
        int nowTimeInt = Integer.parseInt(nowTime.replace(":", ""));

        // 当前时间 > 最大时间
        int endTimeInt = Integer.parseInt(timeRangeEndTime.replace(":", ""));
        if (nowTimeInt > endTimeInt) {
            return null;
        }

        // 分钟大于30 往后推2个小时，分钟小于30 往后推1个小时
        int minuteInt = Integer.parseInt(DateUtil.toString(now, "mm"));
        int hourInt = Integer.parseInt(DateUtil.toString(now, "HH"));
        if (minuteInt > 30) {
            hourInt = hourInt + 2;
        } else {
            hourInt = hourInt + 1;
        }

        // 大于23说明不在当天了
        if (hourInt > 23) {
            return null;
        }

        // 处理过的时间 >= 最大时间小时数
        if (hourInt >= Integer.parseInt(timeRangeEndTime.substring(0, timeRangeEndTime.indexOf(":")))) {
            return null;
        }

        // 如果小时数大于 最小时间小时数则 用最新的小时数计算。否则不变
        if (hourInt > Integer.parseInt(timeRangeStartTime.substring(0, timeRangeStartTime.indexOf(":")))) {
            timeRangeStartTime = String.format("%s:%s", hourInt, "00");
        }

        int startTimeIndex = calculateIndex(timeRangeStartTime);
        int endTimeIndex = calculateIndex(timeRangeEndTime);
        char[] timeChars = times.toCharArray();
        for (int i = startTimeIndex; i < endTimeIndex; i++) {
            if (Objects.equals(timeChars[i], AVAILABLE)) {
                return i;
            }
        }
        return null;
    }

    /**
     * @param times
     * @param timeRange 09:00-22:00
     * @return
     */
    private Integer getNowAfterCalculateDefaultDutyTimeIndex(String times, String timeRange) {
        String[] split = timeRange.split("-");
        String timeRangeStartTime = split[0];
        String timeRangeEndTime = split[1];
        int startTimeIndex = calculateIndex(timeRangeStartTime);
        int endTimeIndex = calculateIndex(timeRangeEndTime);
        char[] timeChars = times.toCharArray();
        for (int i = startTimeIndex; i < endTimeIndex; i++) {
            if (Objects.equals(timeChars[i], AVAILABLE)) {
                return i;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        int startTimeIndex = calculateIndex("09:00");
        int endTimeIndex = calculateIndex("22:00");
        System.out.println(OrderConsts.ORDER_SCHE_NONE_TIMES_96.length());
        String substring = OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(startTimeIndex, endTimeIndex);
        String str1 = OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(0, startTimeIndex);
        String str2 = OrderConsts.ORDER_SCHE_NONE_TIMES_96.substring(endTimeIndex, OrderConsts.ORDER_SCHE_NONE_TIMES_96.length());
        System.out.println(str1.length());
        System.out.println(str2.length());
        System.out.println(substring.length());
        System.out.println((substring+str1+str2).length());

        String timeRange = "09:00-22:00";
        String[] split = timeRange.split("-");
        String timeRangeStartTime = split[0];
        String timeRangeEndTime = split[1];
        System.out.println(timeRangeEndTime.replace(":", ""));
        System.out.println(timeRangeEndTime);

        System.out.println(timeRangeEndTime.substring(0, timeRangeEndTime.indexOf(":")));

        System.out.println(calculateTime(64));
        System.out.println("测试" + DateUtil.toString(new ZsOrderWorkStockScheduleBServiceImpl().calculateDefaultDutyTime("000011111111111111111111111111111111000000001111111111111111001111111111111111111111111111110000", 6, DateUtil.parse("2022-01-21 00:47:09"))));
    }

    /**
     *计算刻度index
     * @param time HH:mm
     * @return
     */
    private static int calculateIndex(String time) {
        String[] split = time.split(":");
        int timeHour = Integer.parseInt(split[0]);
        int timeMinute = Integer.parseInt(split[1]);
        int minuteIndex = timeMinute / 15;
        return timeHour * 4 + minuteIndex;
    }

    /**
     * 计算时间
     * @param index
     * @return time 格式 HH:mm
     */
    private static String calculateTime(int index){
        int minute = (index % 4) * 15;
        int hour = 0;
        if (index > 4) {
            hour = index / 4;
        }
        String minuteStr = minute == 0 ? "00" : String.valueOf(minute);
        String hourStr;
        if (hour == 0) {
            hourStr = "00";
        } else if (hour < 10) {
            hourStr = String.format("%s%s", "0", hour);
        }else {
            hourStr = String.valueOf(hour);
        }
        return String.format("%s:%s", hourStr, minuteStr);
    }

    /**
     * 处理产品数量（涉及拆单）
     * @param distributeMasterQueryBaseBO
     */
    private void processProductNumber(DistributeMasterQueryBaseBO distributeMasterQueryBaseBO) throws OmsBaseException {
        List<PreOrderProductNumberQueryDIO> dioList = new ArrayList<>();
        PreOrderProductNumberQueryDIO dio = new PreOrderProductNumberQueryDIO();
        dio.setBizType(distributeMasterQueryBaseBO.getBizType());
        dio.setChannelId(distributeMasterQueryBaseBO.getChannelId());
        dio.setCityId(distributeMasterQueryBaseBO.getCityId());
        Integer productId = Optional.ofNullable(distributeMasterQueryBaseBO.getProductId()).orElse(distributeMasterQueryBaseBO.getShowProductId());
        dio.setProductId(productId);
        dio.setProductNumber(distributeMasterQueryBaseBO.getProductNumber());
        dioList.add(dio);
        log.info("orderListRemoteService.listPreOrderProductNumber dioList={}", dioList);
        ResponseDTO<List<PreOrderProductNumberDRO>> listResponseDTO = orderListRemoteService.listPreOrderProductNumber(dioList);
        log.info("orderListRemoteService.listPreOrderProductNumber listResponseDTO={}", listResponseDTO);
        if (!listResponseDTO.isSuccess()) {
            throw new OmsBaseException(listResponseDTO.getMessage());
        }
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return;
        }
        Map<Integer, PreOrderProductNumberDRO> droMap = Maps.uniqueIndex(listResponseDTO.getData(), PreOrderProductNumberDRO::getProductId);
        PreOrderProductNumberDRO preOrderProductNumberDRO = droMap.get(productId);
        if (Objects.isNull(preOrderProductNumberDRO)) {
            return;
        }

        distributeMasterQueryBaseBO.setProductNumber(preOrderProductNumberDRO.getProductNumber());
    }

    private void listProcessProductNumber(DistributeMasterQueryBaseBO... distributeMasterQueryBaseBOList) throws OmsBaseException {
        List<PreOrderProductNumberQueryDIO> dioList = new ArrayList<>();
        for (DistributeMasterQueryBaseBO distributeMasterQueryBaseBO : distributeMasterQueryBaseBOList) {
            PreOrderProductNumberQueryDIO dio = new PreOrderProductNumberQueryDIO();
            dio.setBizType(distributeMasterQueryBaseBO.getBizType());
            dio.setChannelId(distributeMasterQueryBaseBO.getChannelId());
            dio.setCityId(distributeMasterQueryBaseBO.getCityId());
            Integer productId = Optional.ofNullable(distributeMasterQueryBaseBO.getProductId()).orElse(distributeMasterQueryBaseBO.getShowProductId());
            dio.setProductId(productId);
            dioList.add(dio);
        }
        log.info("orderListRemoteService.listPreOrderProductNumber dioList={}", dioList);
        ResponseDTO<List<PreOrderProductNumberDRO>> listResponseDTO = orderListRemoteService.listPreOrderProductNumber(dioList);
        log.info("orderListRemoteService.listPreOrderProductNumber listResponseDTO={}", listResponseDTO);
        if (!listResponseDTO.isSuccess()) {
            throw new OmsBaseException(listResponseDTO.getMessage());
        }
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            return;
        }
        Map<Integer, PreOrderProductNumberDRO> droMap = Maps.uniqueIndex(listResponseDTO.getData(), PreOrderProductNumberDRO::getProductId);
        for (DistributeMasterQueryBaseBO distributeMasterQueryBaseBO : distributeMasterQueryBaseBOList) {
            Integer productId = Optional.ofNullable(distributeMasterQueryBaseBO.getProductId()).orElse(distributeMasterQueryBaseBO.getShowProductId());
            PreOrderProductNumberDRO preOrderProductNumberDRO = droMap.get(productId);
            if (Objects.isNull(preOrderProductNumberDRO)) {
                continue;
            }
            distributeMasterQueryBaseBO.setProductNumber(preOrderProductNumberDRO.getProductNumber());
        }
    }
    /**
     * 处理参数
     * @param distributeMasterQueryBaseBO
     */
    public void processDistributeMasterQuery(DistributeMasterQueryBaseBO distributeMasterQueryBaseBO) {
        distributeMasterQueryBaseBO.setGridDistribute(true);
        ProductBO showProductBO = new ProductBO();
        ProductBO productBO = new ProductBO();
        if (NumberUtil.isNotNullOrZero(distributeMasterQueryBaseBO.getShowProductId())) {
            showProductBO = this.getShowProductByProductId(distributeMasterQueryBaseBO.getShowProductId());
        }
        if (NumberUtil.isNotNullOrZero(distributeMasterQueryBaseBO.getProductId())) {
            productBO = this.getProductByProductId(distributeMasterQueryBaseBO.getProductId());

            // 设置前台产品
            showProductBO = this.getShowProductByProductId(distributeMasterQueryBaseBO.getProductId());
        }
        distributeMasterQueryBaseBO.setCategId(productBO.getCategId());
        distributeMasterQueryBaseBO.setShowCategId(showProductBO.getCategId());
        distributeMasterQueryBaseBO.setShowCategOneId(showProductBO.getCategOneId());
        distributeMasterQueryBaseBO.setProductGroupId(productBO.getProductGroupId());
        distributeMasterQueryBaseBO.setShowProductGroupId(showProductBO.getProductGroupId());
        distributeMasterQueryBaseBO.setMainSkillId(distributeMasterQueryBaseBO.getServCategId() + "-" + distributeMasterQueryBaseBO.getShowCategId());

        if (NumberUtil.isNotNullOrZero(productBO.getCategId())) {
            // 后台产品分组
            log.info("servAssCategoryListRemoteService#getProductGroupByCategId 查询产品分组 入参：servCateg={}, categTwoId={}", distributeMasterQueryBaseBO.getServCategId(), productBO.getCategId());
            CategProductGroupQuery categProductGroupQuery = new CategProductGroupQuery();
            categProductGroupQuery.setServCategId(distributeMasterQueryBaseBO.getServCategId());
            categProductGroupQuery.setCategId(productBO.getCategId());
            categProductGroupQuery.setBizType(distributeMasterQueryBaseBO.getBizType());
            categProductGroupQuery.setShowType(BaseProductConsts.ERP_SHOW_TYPE);

            ResponseDTO<CategProductGroupDRO> categoryProductGroupDROResponseDTO = categServProductListRemoteService.getBasisProductGroupByQuery(categProductGroupQuery);
            log.info("servAssCategoryListRemoteService#getProductGroupByCategId 查询产品分组 出参：【{}】", categoryProductGroupDROResponseDTO);
            CategProductGroupDRO categorySimpleProductGroupDRO = categoryProductGroupDROResponseDTO.getData();
            if (categorySimpleProductGroupDRO != null) {
                distributeMasterQueryBaseBO.setServProductGroupId(categorySimpleProductGroupDRO.getGroupId());
            }
        } else if (NumberUtil.isNotNullOrZero(showProductBO.getCategId())) {
            // 前台产品分组
            log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 入参：servCateg={}, categTwoId={}", distributeMasterQueryBaseBO.getServCategId(), showProductBO.getCategId());
            CategProductGroupQuery categProductGroupQuery = new CategProductGroupQuery();
            categProductGroupQuery.setServCategId(distributeMasterQueryBaseBO.getServCategId());
            categProductGroupQuery.setCategId(showProductBO.getCategId());
            categProductGroupQuery.setBizType(distributeMasterQueryBaseBO.getBizType());
            categProductGroupQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
            ResponseDTO<CategProductGroupDRO> responseDTO = categServProductListRemoteService.getBasisProductGroupByQuery(categProductGroupQuery);
            log.info("servAssCategoryListRemoteService#getProductGroupByShowCategId 查询产品分组 出参：【{}】", responseDTO);
            CategProductGroupDRO categorySimpleProductGroupDRO = responseDTO.getData();
            if (categorySimpleProductGroupDRO != null) {
                distributeMasterQueryBaseBO.setServProductGroupId(categorySimpleProductGroupDRO.getGroupId());
            }
        }

        // 行政子公司id
        this.processGridCompanyId(distributeMasterQueryBaseBO);
    }

    private void processGridCompanyId(DistributeMasterQueryBaseBO distributeMasterQueryBaseBO){
        GridCompanyQueryBO gridCompanyQueryBO = new GridCompanyQueryBO();
        gridCompanyQueryBO.setCityId(distributeMasterQueryBaseBO.getCityId());
        gridCompanyQueryBO.setDistributeWay(OrderDistributeConsts.DISTRIBUTE_WAY_PLAT);
        gridCompanyQueryBO.setLongitude(distributeMasterQueryBaseBO.getLongitude());
        gridCompanyQueryBO.setLatitude(distributeMasterQueryBaseBO.getLatitude());
        gridCompanyQueryBO.setServCategId(distributeMasterQueryBaseBO.getServCategId());
        gridCompanyQueryBO.setShowCategId(distributeMasterQueryBaseBO.getShowCategId());
        gridCompanyQueryBO.setShowCategOneId(distributeMasterQueryBaseBO.getShowCategOneId());

        GridCompanyInfoDTO gridCompanyInfo = zsOrderBService.getGridCompanyInfo(gridCompanyQueryBO);

        distributeMasterQueryBaseBO.setGridCompanyId(gridCompanyInfo.getGridCompanyId());
    }

    /**
     * 获取前台产品
     * @param productId
     * @return
     */
    private ProductBO getShowProductByProductId(Integer productId) {
        if (NumberUtil.isNullOrZero(productId)) {
            return null;
        }

        ProductBO bo = new ProductBO();

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        log.info("#获取产品接口productListRemoteService#listBaseDROByDIO#入参[{}],出参[{}]", productDIO, productRemote);
        List<ProductBaseDRO> servProductDROS = productRemote.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            log.error("[{}]产品不存在", productId);
            return null;
        }

        ProductBaseDRO productBaseDRO = servProductDROS.get(0);
        if (Objects.equals(productBaseDRO.getShowType(), BaseProductConsts.EC_SHOW_TYPE)) {
            bo = BeanMapper.map(productBaseDRO, ProductBO.class);
            bo.setProductGroupId(productBaseDRO.getFicoCategId());
            bo.setProductGroupName(productBaseDRO.getFicoCategName());

        } else {
            // 后端产品找前端产品
            DefaultEcProductQuery defaultEcProductQuery = new DefaultEcProductQuery();
            defaultEcProductQuery.setProductIdList(Lists.newArrayList(productBaseDRO.getProductId()));
            defaultEcProductQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
            com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> showProductRemote = productForeignListRemoteService.listEcErpProductByQuery(defaultEcProductQuery);
            if (!CollectionUtils.isEmpty(showProductRemote.getData())) {
                bo = BeanMapper.map(showProductRemote.getData().get(0), ProductBO.class);
                bo.setProductGroupId(productBaseDRO.getFicoCategId());
                bo.setProductGroupName(productBaseDRO.getFicoCategName());
            } else {
                log.error("后端产品[{}]未找到前端产品", productId);
            }
        }
        return bo;
    }

    /**
     * 获取后端产品
     * @param productId
     * @return
     */
    protected ProductBO getProductByProductId(Integer productId) {
        if (NumberUtil.isNullOrZero(productId)) {
            return null;
        }

        ProductBO bo = new ProductBO();

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        log.info("#获取产品接口productListRemoteService#listBaseDROByDIO#入参[{}],出参[{}]", productDIO, productRemote);
        List<ProductBaseDRO> servProductDROS = productRemote.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            log.error("[{}]产品不存在", productId);
            return null;
        }

        ProductBaseDRO productBaseDRO = servProductDROS.get(0);
        if (Objects.equals(productBaseDRO.getShowType(), BaseProductConsts.ERP_SHOW_TYPE)) {
            bo = BeanMapper.map(productBaseDRO, ProductBO.class);
            bo.setProductGroupId(productBaseDRO.getFicoCategId());
            bo.setProductGroupName(productBaseDRO.getFicoCategName());
        }
        return bo;
    }
}